#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QQuickStyle>
#include <QQuickWindow>
#include <QSystemTrayIcon>
#include <QTimer>
#include "files/file_system_model.h"
#include "files/kms_file_system_watcher.h"
#include "service/system_icon_provider.h"
#include "service/icon_image_provider.h"
#include "database/database_manager.h"
#include "service/backend_service.h"
#include "service/mouse_position.h"
#include "service/web_socket_server.h"
#include "service/runtime_file_system_watcher.h"
#include "service/system_tray_manager.h"
#include "command/command_executor.h"
#include "command/access_token_timer.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    // 设置为非原生风格，例如使用Fusion风格
    QQuickStyle::setStyle("Fusion");

    // 注册 C++ 类型到 QML
    qmlRegisterType<FileSystemModel>("FileSystemModel", 1, 0, "FileSystemModel");
    qmlRegisterType<SystemIconProvider>("SystemIconProvider", 1, 0, "SystemIconProvider");
    qmlRegisterType<DatabaseManager>("DatabaseManager", 1, 0, "DatabaseManager");
    qmlRegisterType<BackendService>("BackendService", 1, 0, "BackendService");
    qmlRegisterType<MousePosition>("MousePosition", 1, 0, "MousePosition");
    qmlRegisterType<WebSocketServer>("WebSocketServer", 1, 0, "WebSocketServer");
    qmlRegisterType<SystemTrayManager>("SystemTrayManager", 1, 0, "SystemTrayManager");

    QQmlApplicationEngine engine;
    
    // 注册图标提供器
    engine.addImageProvider("icon", new IconImageProvider);
    
    // 创建全局实例（使用 new 确保对象生命周期）
    DatabaseManager *databaseManager = new DatabaseManager(&app);

    FileSystemModel *fileSystemModel = new FileSystemModel(databaseManager, &app);
    SystemIconProvider *systemIconProvider = new SystemIconProvider(&app);

    BackendService *backendService = new BackendService(&app);
    MousePosition *mousePosition = new MousePosition(&app);
    WebSocketServer *webSocketServer = new WebSocketServer(&app);
    RuntimeFileSystemWatcher *runtimeFileSystemWatcher = new RuntimeFileSystemWatcher(&app);
    KmsFileSystemWatcher *kmsFileSystemWatcher = new KmsFileSystemWatcher(&app);
    SystemTrayManager *systemTrayManager = new SystemTrayManager(&app);
    
    // 创建 CommandExecutor 实例（用于 BackendService 的 syncDisks 功能）
    CommandExecutor *commandExecutor = new CommandExecutor(&app);
    
    // 创建 AccessTokenTimer 实例（用于定时刷新 AccessToken）
    AccessTokenTimer *accessTokenTimer = new AccessTokenTimer(&app);
    
    // 启动 WebSocket 服务器（监听 9038 端口）
    if (webSocketServer->startServer(9038)) {
        qDebug() << "WebSocket 服务器已成功启动在端口 9038";
    } else {
        qDebug() << "WebSocket 服务器启动失败";
    }
    
    // 应用启动时立即初始化数据库
    if (databaseManager->initializeDatabase()) {
        qDebug() << "数据库初始化成功";
    } else {
        qDebug() << "数据库初始化失败";
    }
    
    // 设置数据库管理器到BackendService
    backendService->setDatabaseManager(databaseManager);
    
    // 设置 QML 引擎到 BackendService
    backendService->setQmlEngine(&engine);
    
    // 设置 CommandExecutor 到 BackendService（用于 syncDisks 功能）
    commandExecutor->setBackendService(backendService);
    commandExecutor->setDatabaseManager(databaseManager);
    commandExecutor->setWebSocketServer(webSocketServer);
    backendService->setCommandExecutor(commandExecutor);
    
    // 设置数据库管理器到RuntimeFileSystemWatcher
    runtimeFileSystemWatcher->setDatabaseManager(databaseManager);
    
    // 设置数据库管理器到KmsFileSystemWatcher
    kmsFileSystemWatcher->setDatabaseManager(databaseManager);
    
    // 设置 BackendService 到 RuntimeFileSystemWatcher
    runtimeFileSystemWatcher->setBackendService(backendService);
    
    // 设置 WebSocketServer 到 RuntimeFileSystemWatcher
    runtimeFileSystemWatcher->setWebSocketServer(webSocketServer);
    
    // 设置 BackendService 到 WebSocketServer
    webSocketServer->setBackendService(backendService);
    
    // 设置 BackendService 到 SystemTrayManager（用于检查登录状态）
    systemTrayManager->setBackendService(backendService);
    
    // 设置 AccessTokenTimer 的 BackendService 和 NetworkAccessManager
    accessTokenTimer->setBackendService(backendService);
    accessTokenTimer->setNetworkAccessManager(commandExecutor->getNetworkAccessManager());
    
    // 启动 RuntimeFileSystemWatcher 监听 runtime 目录
    runtimeFileSystemWatcher->startWatching();
    qDebug() << "RuntimeFileSystemWatcher 已启动，监听目录:" << runtimeFileSystemWatcher->getRuntimeDirectory();

    // 启动 KmsFileSystemWatcher 监听用户工作目录
    kmsFileSystemWatcher->startWatching(backendService->getUserWorkBaseDir());
    qDebug() << "KmsFileSystemWatcher 已启动，监听目录:" << kmsFileSystemWatcher->getWatchedDirectory();
    
    
    // 连接CommandExecutor的同步完成信号到FileSystemModel刷新（用于SyncDisksCommand）
    QObject::connect(commandExecutor, &CommandExecutor::syncDisksCompleted,
                     fileSystemModel, [fileSystemModel](int resultCode, const QString &message) {
                         if (resultCode == 0) {
                             qDebug() << "网盘同步完成（通过CommandExecutor），刷新文件系统模型";
                             fileSystemModel->refresh();
                         } else {
                             qDebug() << "网盘同步失败（通过CommandExecutor），不刷新文件系统模型:" << message;
                         }
                     });
    
    QObject::connect(commandExecutor, &CommandExecutor::syncFoldersCompleted,
                     fileSystemModel, [fileSystemModel](int resultCode, const QString &message) {
                         if (resultCode == 0) {
                             qDebug() << "文件夹同步完成，刷新文件系统模型";
                             fileSystemModel->refresh();
                         } else {
                             qDebug() << "文件夹同步失败，不刷新文件系统模型:" << message;
                         }
                     });
    
    QObject::connect(commandExecutor, &CommandExecutor::syncFilesCompleted,
                     fileSystemModel, [fileSystemModel](int resultCode, const QString &message) {
                         if (resultCode == 0) {
                             qDebug() << "文件同步完成（通过CommandExecutor），刷新文件系统模型";
                             fileSystemModel->refresh();
                         } else {
                             qDebug() << "文件同步失败（通过CommandExecutor），不刷新文件系统模型:" << message;
                         }
                     });
    
    // 连接文件下载完成信号到FileSystemModel刷新
    QObject::connect(commandExecutor, &CommandExecutor::downloadFileCompleted,
                     fileSystemModel, [fileSystemModel](int resultCode, const QString &message, const QString &filePath) {
                         if (resultCode == 0) {
                             qDebug() << "文件下载完成（通过CommandExecutor），刷新文件系统模型，文件路径:" << filePath;
                             fileSystemModel->refresh();
                         } else {
                             qDebug() << "文件下载失败（通过CommandExecutor），不刷新文件系统模型:" << message;
                         }
                     });

    // 注意：fileDownloadedForUrl信号已废弃（URL字段已移除），文件状态更新已在下载成功后直接完成

    // 文件状态或本地信息发生变化时，刷新文件系统模型（用于更新图标状态等）
    QObject::connect(databaseManager, &DatabaseManager::filesChanged,
                     fileSystemModel, &FileSystemModel::refresh);
    
    QObject::connect(fileSystemModel, &FileSystemModel::filesChanged,
                     fileSystemModel, &FileSystemModel::refresh);
    
    
    // 将实例设置为 QML 上下文属性
    engine.rootContext()->setContextProperty("fileSystemModel", fileSystemModel);
    engine.rootContext()->setContextProperty("systemIconProvider", systemIconProvider);
    engine.rootContext()->setContextProperty("databaseManager", databaseManager);
    engine.rootContext()->setContextProperty("backendService", backendService);
    engine.rootContext()->setContextProperty("commandExecutor", commandExecutor);
    engine.rootContext()->setContextProperty("mousePosition", mousePosition);
    engine.rootContext()->setContextProperty("webSocketServer", webSocketServer);
    engine.rootContext()->setContextProperty("runtimeFileSystemWatcher", runtimeFileSystemWatcher);
    engine.rootContext()->setContextProperty("systemTrayManager", systemTrayManager);
    
    QObject::connect(
        &engine,
        &QQmlApplicationEngine::objectCreationFailed,
        &app,
        []() { QCoreApplication::exit(-1); },
        Qt::QueuedConnection);
    
    // 显示托盘图标
    systemTrayManager->showTrayIcon();
    
    // 连接托盘图标激活信号（双击事件）
    QObject::connect(systemTrayManager, &SystemTrayManager::trayIconActivated,
                     [backendService](QSystemTrayIcon::ActivationReason reason) {
        if (reason == QSystemTrayIcon::DoubleClick) {
            qDebug() << "托盘图标被双击";
            
            // 检查是否已登录
            bool loggedIn = backendService->isLoggedIn();
            qDebug() << "当前登录状态:" << (loggedIn ? "已登录" : "未登录");
            
            // 根据登录状态获取或创建窗口
            QString windowTitle = loggedIn ? "Main" : "Login";
            QQuickWindow *window = backendService->getOrCreateWindow(windowTitle);
            
            // 显示并激活窗口，确保显示在最上层
            if (window) {
                window->show();
                window->raise();
                window->requestActivate();
            }
        }
    });
    
    // 连接显示窗口请求信号
    QObject::connect(systemTrayManager, &SystemTrayManager::showWindowRequested,
                     [backendService]() {
        qDebug() << "收到显示窗口请求";
        
        // 检查是否已登录
        bool loggedIn = backendService->isLoggedIn();
        qDebug() << "当前登录状态:" << (loggedIn ? "已登录" : "未登录");
        
        // 根据登录状态获取或创建窗口
        QString pageName = loggedIn ? "Main" : "Login";
        QQuickWindow *window = backendService->getOrCreateWindow(pageName);
        
        // 显示并激活窗口，确保显示在最上层
        if (window) {
            // 如果窗口最小化，先恢复
            if (window->windowState() & Qt::WindowMinimized) {
                window->showNormal();
            }
            window->show();
            window->raise();
            window->requestActivate();
        }
    });

    // 连接退出请求信号
    QObject::connect(systemTrayManager, &SystemTrayManager::quitRequested,
                     &app, &QCoreApplication::quit);
    
    // 连接登录请求信号
    QObject::connect(systemTrayManager, &SystemTrayManager::loginRequested,
                     [backendService]() {
        qDebug() << "收到登录请求";
        
        // 显示登录窗口
        QQuickWindow *loginWindow = backendService->getOrCreateWindow("Login");
        if (loginWindow) {
            // 如果窗口最小化，先恢复
            if (loginWindow->windowState() & Qt::WindowMinimized) {
                loginWindow->showNormal();
            }
            loginWindow->show();
            loginWindow->raise();
            loginWindow->requestActivate();
        }
    });
    
    // 连接注销请求信号
    QObject::connect(systemTrayManager, &SystemTrayManager::logoutRequested,
                     [backendService, systemTrayManager, accessTokenTimer]() {
        qDebug() << "收到注销请求";
        
        // 停止 AccessTokenTimer（注销时停止定时刷新）
        if (accessTokenTimer && accessTokenTimer->isActive()) {
            accessTokenTimer->stop();
            qDebug() << "AccessTokenTimer 已停止";
        }
        
        // 执行注销操作
        backendService->logout();
        
        // 更新托盘菜单（隐藏注销菜单项）
        systemTrayManager->updateMenu(false);
        
        // 关闭主窗口（如果存在）
        QQuickWindow *mainWindow = backendService->getOrCreateWindow("Main");
        if (mainWindow) {
            mainWindow->close();
        }
        
        // 显示登录窗口
        QQuickWindow *loginWindow = backendService->getOrCreateWindow("Login");
        if (loginWindow) {
            loginWindow->show();
            loginWindow->raise();
            loginWindow->requestActivate();
        }
        
        qDebug() << "注销完成";
    });
    
    // 监听登录结果，更新托盘菜单（通过 CommandExecutor）
    QObject::connect(commandExecutor, &CommandExecutor::loginResult,
                     [systemTrayManager, backendService, accessTokenTimer](int resultCode, const QString &message, const QStringList &domains) {
        if (resultCode == 0) {
            // 登录成功，显示注销菜单项
            qDebug() << "登录成功，更新托盘菜单显示注销选项";
            systemTrayManager->updateMenu(true);
            
            // 启动 AccessTokenTimer（登录成功后开始定时刷新）
            if (accessTokenTimer && !accessTokenTimer->isActive()) {
                accessTokenTimer->start();
                qDebug() << "AccessTokenTimer 已启动，将每1小时自动刷新 AccessToken";
            }
        } else {
            // 登录失败，隐藏注销菜单项
            qDebug() << "登录失败，隐藏注销菜单项";
            systemTrayManager->updateMenu(false);
            
            // 停止 AccessTokenTimer（登录失败时停止定时刷新）
            if (accessTokenTimer && accessTokenTimer->isActive()) {
                accessTokenTimer->stop();
                qDebug() << "AccessTokenTimer 已停止";
            }
        }
    });
    
    // 监听自动登录成功（exchangeAccessTokenCompleted），更新托盘菜单（通过 CommandExecutor）
    QObject::connect(commandExecutor, &CommandExecutor::exchangeAccessTokenCompleted,
                     [systemTrayManager, backendService, accessTokenTimer](int resultCode, const QString &message, const QString &accessToken) {
        if (resultCode == 0 && !accessToken.isEmpty()) {
            // 检查是否是自动登录场景（AutoLogin=true）
            bool autoLogin = backendService->loadAutoLogin();
            if (autoLogin) {
                // 自动登录成功，检查登录状态并更新托盘菜单
                bool isLoggedIn = backendService->isLoggedIn();
                if (isLoggedIn) {
                    qDebug() << "自动登录成功，更新托盘菜单和 tooltip";
                    systemTrayManager->updateMenu(true);
                }
            }
            
            // 启动 AccessTokenTimer（登录成功后开始定时刷新）
            if (accessTokenTimer && !accessTokenTimer->isActive()) {
                accessTokenTimer->start();
                qDebug() << "AccessTokenTimer 已启动，将每1小时自动刷新 AccessToken";
            }
        }
    });
    
    // 初始化托盘菜单状态（根据当前登录状态）
    bool initialLoginState = backendService->isLoggedIn();
    systemTrayManager->updateMenu(initialLoginState);
    qDebug() << "初始化托盘菜单，登录状态:" << (initialLoginState ? "已登录" : "未登录");
    
    // 如果应用启动时已经登录，启动 AccessTokenTimer
    if (initialLoginState) {
        if (accessTokenTimer && !accessTokenTimer->isActive()) {
            accessTokenTimer->start();
            qDebug() << "应用启动时已登录，AccessTokenTimer 已启动，将每1小时自动刷新 AccessToken";
        }
    }
    
    
    // 应用启动时，判断 setting.ini 中 AutoLogin=true 则立即执行登录
    backendService->tryAutoLogin();

    // 用隐藏方式加载登录页面 保证双击托盘图标时，登录页面会显示在最上层
    // engine.loadFromModule("desktop", "Login");

    return app.exec();
}
